﻿using System;
using UnityEngine;

namespace BF
{
    /// <summary>
    /// 用户数据，用于存放到本地
    /// </summary>
    [Serializable]
    public abstract class PlayerDataInfo
    {
#if DEBUG
        /// <summary>
        /// 警告，不要随意使用，false会导致用户无法存储本地数据
        /// 只能在Debug模式下使用
        /// </summary>
        [NonSerialized]
        public static bool isEnableSave = true;
#endif
        /// <summary>
        /// PlayerPrefs Key
        /// </summary>
        [NonSerialized]
        private string _prefsKey;

        /// <summary>
        /// 上一次储存的数据
        /// 用于判断若2次数据一样，则不重复存储
        /// </summary>
        [NonSerialized]
        private string _lastSaveStr;
        /// <summary>
        /// 是否自动保存
        /// </summary>
        public abstract bool isAutoSave { get; }

        /// <summary>
        /// 保存数据到本地
        /// </summary>
        public virtual void Save()
        {
#if DEBUG
            if (!isEnableSave)
            {
                return;
            }
#endif
            try
            {
                DoSave(_prefsKey, this);
            }
            catch (Exception e)
            {
                Debug.LogError($"[PlayerDataInfo] [Save] error: key:{_prefsKey}, {e}");
            }
        }

        /// <summary>
        /// 每次实例化对象后执行
        /// 主要用于不同版本间的数据兼容
        /// </summary>
        protected virtual void CheckValue()
        {

        }

        public static T Load<T>() where T : PlayerDataInfo, new()
        {
            string key = $"PDI_{typeof(T).Name}";
            if (PlayerPrefs.HasKey(key))
            {
                try
                {
                    T t = DoLoad<T>(key);
                    t._prefsKey = key;
                    t.CheckValue();
                    return t;
                }
                catch (Exception e)
                {
                    Debug.LogError($"[PlayerDataInfo] [Load] error: key:{key}, {e}");

                    return New<T>();
                }
            }
            else
            {
                return New<T>();
            }
        }

        public static T New<T>() where T : PlayerDataInfo, new()
        {
            T t = new T();
            t._prefsKey = $"PDI_{typeof(T).Name}";
            t.CheckValue();
            t.Save();
            return t;
        }


        /// <summary>
        /// 读取本地数据，并反序列化
        /// </summary>
        private static T DoLoad<T>(string key) where T : PlayerDataInfo, new()
        {
            string str = PlayerPrefs.GetString(key);
            return SerializeUtil.Deserialize<T>(str);
        }

        /// <summary>
        /// 将对象序列化，并存储到本地
        /// </summary>
        private static void DoSave(string key, PlayerDataInfo t)
        {
            string str = SerializeUtil.SerializeToString(t);
            if (t._lastSaveStr == null || !str.Equals(t._lastSaveStr))
            {
                PlayerPrefs.SetString(key, str);
                t._lastSaveStr = str;
            }
        }
    }
}